// OCR任务的标注结果
import labelDef from './Def';
import LabelConfig from '@/js/models/LabelConfig';
import { LabelBase } from '@/js/models/LabelBase';
import { getCurrentTime } from '@/js/utils/baseUtils';
import { calcPolyPoints, getPointsLT, calculatePolygonBounds } from '@/js/utils/geomUtils';
import { getImageCoords, getCanvasCoords } from '@/js/utils/imageUtils';
import { setFObjectEditable, newRectFObject, newPolyFObject } from '@/js/utils/FabricControls';

export default class LabelOCR extends LabelBase {
    constructor(label_format) {
        super(label_format);

        this.labels_geom = [];
        this.last_selected_geom = null;
        this.tools_callback = {
            rect: this.rectToolCallback.bind(this),
            poly: this.polyToolCallback.bind(this)
        };

        // 在组件中增加遮罩层相关变量
        this.highlight = false;
        this.mask_layer = null;
        this.MASK_COLOR = 'rgba(0, 0, 0, 0.7)';
    }

    ///====================以下定义geom显示相关的处理函数========================
    // 在canvas中渲染结果
    bindCanvas(canvas, image, label_tools) {
        // console.log('bindCanvas canvas = ', canvas);
        super.bindCanvas(canvas, image, label_tools);

        // 加载labels中的数据
        for (let i = 0; i < this.labels.length; i++) {
            let label = this.labels[i];
            if (!label || !label.data || !label.data.points) continue;
            let points = getCanvasCoords(this.image, label.data.points);
            let pt_tl = getPointsLT(points);
            let poly = newPolyFObject(label.id, 0, { points: points, left: pt_tl.x, top: pt_tl.y }, LabelConfig.getConfig('displaySeg'));

            this.canvas.add(poly);
            this.labels_geom[label.id] = poly;
            this.registerObjectEvents(poly);
        }

        // 初始化遮罩层
        this.initMask();

        // 刷新显示
        this.canvas.requestRenderAll();

        return true;
    }

    rectToolCallback(rect) {
        // console.log('LabelOCR::rectToolCallback rect = ', rect, ' this = ', this);
        let label_id = Object.keys(this.labels_geom).length;
        this.label_panel &&
            this.label_panel.showEditDialog('rect', label_id, (form) => {
                console.log('rectToolCallback form = ', form, ', rect = ', rect);
                let poly = {
                    left: rect.left,
                    top: rect.top,
                    points: [
                        { x: rect.left, y: rect.top },
                        { x: rect.left + rect.width, y: rect.top },
                        { x: rect.left + rect.width, y: rect.top + rect.height },
                        { x: rect.left, y: rect.top + rect.height }
                    ]
                };
                this.newPolyLabel(poly, form);
            });
    }

    polyToolCallback(poly) {
        let label_id = Object.keys(this.labels_geom).length;
        this.label_panel &&
            this.label_panel.showEditDialog('rect', label_id, (form) => {
                console.log('polyToolCallback form = ', form, ', poly = ', poly);
                this.newPolyLabel(poly, form);
            });
    }

    newPolyLabel(poly, form) {
        // console.log(form);
        // 创建新的polygon对象
        let label_id = Object.keys(this.labels_geom).length;
        let poly_new = newPolyFObject(label_id, 0, poly);
        poly_new.set({ selectable: false, evented: false });
        // console.log(poly_new);

        // 添加polygon到canvas上
        this.canvas.add(poly_new);
        this.labels_geom[label_id] = poly_new;
        this.registerObjectEvents(poly_new);

        // 在数据中增加新增多边形
        let points = getImageCoords(this.image, poly.points);
        let data = {};
        Object.assign(data, form);
        data.id = label_id;
        data.label_format = this.label_format;
        data.points = points;
        data.text = form.text;
        // 构建bbox
        let { left, top, right, bottom } = calculatePolygonBounds(poly.points);
        let pts = [
            { x: left, y: top },
            { x: right, y: bottom }
        ];
        let pts_bbox = getImageCoords(this.image, pts);
        let bbox = [pts_bbox[0].x, pts_bbox[0].y, pts_bbox[1].x, pts_bbox[1].y];
        data.bbox = bbox;
        this.addLabel(data);

        // 在label_panel中增加新增矩形框
        this.label_panel && this.label_panel.addLabel(data);
    }

    // geom: fabricjs的对象，代表rect或者poly
    // data: 标注的基础数据，例如class、ocrtext等
    newLabelData(geom, text = undefined) {
        // console.log(geom);
        let pts = [];
        let label_data = {};
        if (geom && geom.type == 'rect') {
            pts = [geom.aCoords.tl, geom.aCoords.tr, geom.aCoords.br, geom.aCoords.bl];
            label_data.id = geom.label_id;
            label_data.points = getImageCoords(_image, pts);
            label_data.text = text;
            emit('addLabel', label_data);
        } else if (geom && geom.type == 'polygon') {
            label_data.id = geom.label_id;
            label_data.points = getImageCoords(_image, geom.points);
            label_data.text = text;
            emit('addLabel', label_data);
        }
        return true;
    }

    selectLabel(label_id, target = null) {
        // console.log(`selectLabel label_id = ${label_id}, target = `, target);
        // 在canvas中选择标签对象
        if (!(label_id in this.labels_geom)) {
            return;
        }

        // 取消选择，并根据是否有点击的具体对象，将需要选中的对象都放到selected_geoms中
        this.unselectLabel();

        // 放置待选择的对象
        let select_geom = null;
        if (target) {
            select_geom = target;
        } else {
            let geom = this.labels_geom[label_id];
            select_geom = geom;
        }

        select_geom.set({
            fill: 'rgba(200,0,0,0.2)',
            stroke: 'rgba(200,0,0,1.0)'
        });
        setFObjectEditable(select_geom);
        this.canvas.setActiveObject(select_geom);
        this.last_selected_geom = select_geom;
        this.canvas.requestRenderAll();

        // 在label_panel中选择标签对象
        this.label_panel && this.label_panel.selectLabel(label_id);
    }

    unselectLabel() {
        // 在canvas中取消选择label
        // console.log(`## this.last_selected_geoms = `, this.last_selected_geoms);
        if (this.last_selected_geom) {
            let geom = this.last_selected_geom;
            if (geom && geom.data && geom.data.type === 'bbox' || geom.data.type === 'segm') {
                let type = geom.type;
                let config = {
                    fill: LabelConfig.getConfig(`${type}_style.fill`),
                    strokeWidth: LabelConfig.getConfig(`${type}_style.strokeWidth`),
                    stroke: LabelConfig.getConfig(`${type}_style.stroke`),
                    hasControls: false
                };
                geom.set(config);
            }
            this.last_selected_geom = null;
        }

        // 在label_panel中取消选择panel
        this.label_panel && this.label_panel.selectLabel(-1);
    }

    // 删除当前选中的label
    deleteSelection() {
        // console.log('deleteSelection last_selected_geoms = ', this.last_selected_geoms);
        if (this.last_selected_geom) {
            let label_id = this.last_selected_geom.label_id;
            this.deleteLabel(label_id);
            this.last_selected_geom = null;
        }
    }


    ////////////////////////////////////////////////////////////////////////////////////
    // 定义遮罩相关的处理函数
    onLabelMouseover(event) {
        // console.log(`[ocr]onLabelMouseover event = `, event);
        if (this.highlight && event.target && event.target.type === 'polygon') {
            event.target.hoverCursor = 'pointer';
            this.updateMask(event.target);
            this.canvas.requestRenderAll();
        }
    }

    onLabelMouseout(event) {
        // console.log(`[ocr]onLabelMouseout event = `, event);
        if (this.highlight && event.target && event.target.type === 'polygon') {
            this.updateMask(null);
            this.canvas.requestRenderAll();
        }
    }

    // 设置是否highlight选中对象
    setHighlight() {
        this.highlight = true;
    }

    // 初始化遮罩层
    initMask() {
        if (!this.canvas || !this.image) {
            return;
        }

        this.maskLayer = new fabric.Rect({
            originX: 'center',
            originY: 'center',
            left: this.canvas.width / 2,
            top: this.canvas.height / 2,
            width: this.image.width,
            height: this.image.height,
            fill: this.MASK_COLOR,
            selectable: false,
            evented: false,
            excludeFromExport: true,
            visible: false
        });
        this.canvas.add(this.maskLayer);
    }

    // 更新遮罩层
    updateMask(target) {
        if (!target || !this.canvas || !this.image) {
            this.maskLayer && this.maskLayer.set({ visible: false });
            return;
        }
        // 计算目标对象的包围盒
        const bound = {
            left: target.left,
            top: target.top,
            width: target.width,
            height: target.height
        };
        const clipPath = new fabric.Group(
            [
                // 全屏遮罩
                new fabric.Rect({
                    originX: 'center',
                    originY: 'center',
                    left: this.canvas.width / 2,
                    top: this.canvas.height / 2,
                    width: this.image.width,
                    height: this.image.height,
                    fill: this.MASK_COLOR
                }),
                // 挖空区域（反向蒙版）
                new fabric.Rect({
                    left: bound.left,
                    top: bound.top,
                    width: bound.width,
                    height: bound.height,
                    fill: 'white',
                    globalCompositeOperation: 'destination-out'
                })
            ],
            {
                absolutePositioned: true,
                selectable: false,
                evented: false
            }
        );

        // 更新遮罩层
        this.maskLayer.set({
            visible: true,
            clipPath: clipPath
        });
        this.maskLayer.bringToFront();
    }

    // 设置对象是否可以编辑
    setEditableMode(editable = true) {
        // console.log('setEditableMode editable = ', editable);
        let evented = (!this.highlight && !editable) ? false : true;
        this.unselectLabel();
        for (let i = 0; i < this.labels_geom.length; i++) {
            let geom = this.labels_geom[i];
            if (geom) {
                geom.set({
                    selectable: editable,
                    evented: evented
                });
            }
        }
        this.canvas.requestRenderAll();
    }

    onLabelModified(event) {
        console.log('LabelOCR::onLabelModified event = ', event);
        let label_id = event.target.label_id;
        let geom = this.labels_geom[label_id];
        let update_info = {
            id: label_id
        };
        let points = null;
        if (geom && geom.type == 'rect') {
            points = [geom.aCoords.tl, geom.aCoords.tr, geom.aCoords.br, geom.aCoords.bl];
            points = getImageCoords(this.image, points);
            update_info['points'] = points;
        } else if (geom && geom.type == 'polygon') {
            points = calcPolyPoints(geom.points, { x: geom.left, y: geom.top });
            points = getImageCoords(this.image, points);
            update_info['points'] = points;
        } else {
        }

        console.log('update_info = ', update_info);
        this.updateLabel(update_info);

        // 在label_panel中更新信息
        this.label_panel && this.label_panel.updateStatus();
    }

    ///========================以下定义数据相关的处理函数========================
    // 添加一个文字检测的标注结果
    addLabel(data) {
        console.log('LabelOCR addLabel data = ', data);
        this.labels[data.id] = this.labelOfBase(data.id, 'vision:ocr', labelDef(data));
        this.saved = false;
        return true;
    }

    // 更新对应的labelid信息，可以更新poly或者text文本
    updateLabel(data) {
        // console.log(`LabelOCR::updateLabel data = `, data);
        let labelid = data.id;
        let points = data.points;
        if (labelid in this.labels && this.labels[labelid]) {
            if (points) {
                this.labels[labelid].data.points = points;
            }
            this.labels[labelid].score = 1.0;
            this.labels[labelid].timestamp = getCurrentTime();
            this.saved = false;
            return true;
        } else {
            return false;
        }
    }

    deleteLabel(label_id) {
        // console.log('LabelDetection::deleteLabel label_id = ', label_id);
        // 从canvas中删除
        if (this.canvas && label_id in this.labels_geom) {
            let geom = this.labels_geom[label_id];
            geom && this.canvas.remove(geom);
            this.labels_geom[label_id] = null;
        }

        // 从label_panel中删除
        this.label_panel && this.label_panel.deleteLabel(label_id, false);

        // 从数据中删除
        if (label_id in this.labels) {
            this.labels[label_id] = null;
            this.saved = false;
            return true;
        } else {
            return false;
        }
    }

    fromJson(json_data) {
        // console.log('LabelOCR::fromJson json_data = ', json_data);
        this.labels = [];
        for (let i = 0; i < json_data.length; i++) {
            let data = json_data[i];
            this.labels[data.id] = this.labelOfBase(data.id, 'vision:ocr', data);
        }
    }

    toJson() {
        let results = [];
        for (let i = 0; i < this.labels.length; i++) {
            let label = this.labels[i];
            if (label) {
                label.id = results.length;
                results.push(label);
            }
        }
        let json_str = JSON.stringify(results);
        return json_str;
    }
}
